<template>
    <div class="wrap">
        <div class="d-flex align-items-center d-top">
            <label class="el-form-item__label">{{
                $t('message.materialConsumeStatistics.selectedInstanceNode')
                }}：</label>
            <query-list
                    :tipMsg="$t('message.materialConsumeStatistics.assemblyInstanceNode')"
                    v-model="selectedInstanceNode"
                    :active="queryListActiveMap.selectedInstanceNode"
                    @switchQuery="switchQuery('selectedInstanceNode')">
            </query-list>
        </div>
<!--        <div class="wrap-content">-->
<!--            <el-table :data="tableData" style="width: 100%" :span-method="objectSpanMethod">-->
<!--                <el-table-column prop="partDocName"-->
<!--                                 :label="$t('message.materialConsumeStatistics.partDocName')"></el-table-column>-->
<!--                <el-table-column prop="number"-->
<!--                                 :label="$t('message.materialConsumeStatistics.materialNumber')"></el-table-column>-->
<!--                <el-table-column prop="level" :label="$t('message.materialConsumeStatistics.level')"></el-table-column>-->
<!--                <el-table-column prop="standard"-->
<!--                                 :label="$t('message.materialConsumeStatistics.standard')"></el-table-column>-->
<!--                <el-table-column prop="area" :label="$t('message.materialConsumeStatistics.area')"></el-table-column>-->
<!--                <el-table-column prop="totalArea"-->
<!--                                 :label="$t('message.materialConsumeStatistics.totalArea')"></el-table-column>-->
<!--            </el-table>-->
<!--        </div>-->
        <div class="btn">
            <el-button type="primary" size="small"
                       @click="confirm">{{ $t('message.materialConsumeStatistics.export') }}
            </el-button>
            <el-button size="small"
                       @click="cancel">{{ $t('message.common.cancel') }}
            </el-button>
        </div>
    </div>
</template>

<script>
import InstanceTree from "./AssemblyDocMaterialSetting/InstanceTree.vue";
import PartDocMaterialInfo from "./PartDocMaterialSetting/PartDocMaterialInfo.vue";
import DialogMixin from "../DialogMixin";
import {materialSettingCommand} from "../../../command/MaterialSettingCommand";
import * as XLSX from "xlsx";
import saveAs from 'file-saver';

export default {
    name: "AssemblyDocMaterialStatics",
    mixins: [DialogMixin],
    components: {PartDocMaterialInfo, InstanceTree},
    data() {
        return {
            isInit: false,
            queryListActiveMap: {
                selectedInstanceNode: 1,
            },
            instanceTree: [],
            selectedInstanceNode: [], //选中节点 显示名称
            currentSelectNodeInsInfo: [],//当前选择节点文档信息
            currentSelectNodeMaterialData: [],//当前选择节点材料信息,
            mergeExcel:[],
            tableData: [],
        }
    },
    mounted() {
        if (!this.isInit) {
            materialSettingCommand.init(350, 350, 250, () => {
                this.handlePickInstance();
                this.getInstanceTree();
                this.isInit = true;
            })
        }
    },
    methods: {
        changePluginContainerHeight() {
            materialSettingCommand.changePluginContainerHeight({
                minWidth: this.$el.clientWidth,
                maxHeight: this.$el.clientHeight + 10
            });
        },
        confirm() {
            this.setInsNodeMaterialData();
        },
        cancel() {
            materialSettingCommand.clearAllHighLight();
            materialSettingCommand.closeActiveCmd();
        },
        //当前激活的选取框切换
        switchQuery(name) {
            for (const key in this.queryListActiveMap) {
                if (key === name) {
                    this.queryListActiveMap[key] = 1;
                } else {
                    this.queryListActiveMap[key] = 0;
                }
            }
        },
        //处理拾取的实例节点
        handlePickInstance() {
            materialSettingCommand.handlePickInstance((res) => {
                let instanceItem = res?.instance;//instanceList
                this.selectedInstanceNode = [];
                if (!!instanceItem && instanceItem.length) {
                    if (this.checkSelectedNodeType(instanceItem[0])) {
                        this.selectedInstanceNode = instanceItem;
                    } else {
                        let msg = '请选择装配节点类型';
                        materialSettingCommand.eventBusAlertMsg(msg, 'warning');
                    }
                    //只能选择装配，不能选择零件
                }
            })
        },
        checkSelectedNodeType(node) {
            if (node.type === 'assembly') {
                return true;
            }
            return false;
        },
        getInstanceTree() {
            materialSettingCommand.getInstanceTree(res => {
                //获取实例的id,name,children
                this.instanceTree = res;
            })
        },
        objectSpanMethod({row, column, rowIndex, columnIndex}) {
            let spanOneArr = [];
            let concatOne = 0;
            this.tableData.map((item, index) => {
                if (index === 0) {
                    spanOneArr.push(1);
                } else {
                    if (item.partDocName === this.tableData[index - 1].partDocName) {
                        spanOneArr[concatOne] += 1;
                        spanOneArr.push(0);
                    } else {
                        spanOneArr.push(1);
                        concatOne = index;
                    }
                }
            })
            if (columnIndex === 0) {
                const _row = spanOneArr[rowIndex];
                const _col = _row > 0 ? 1 : 0;
                return {
                    rowspan: _row,
                    colspan: _col
                }
            }
        },
        async setInsNodeMaterialData() {
            if (this.selectedInstanceNode.length) {
                //如果有选择的装配节点，支持导出
                let insId = this.selectedInstanceNode[0].id;
                let insInfo = this.instanceTree.filter(item => item.id === insId)[0];//获取当前装配节点的实例数据（id,name,children）
                let insAndChildIds = this.getChildIds(insInfo);
                let insChildIds = insAndChildIds.filter(item => item !== insId);//获取当前装配节点全部子节点的id列表
                let allInsProtoData = await materialSettingCommand.getInstancesProtoData();
                let insChildRefDocInfo = allInsProtoData.filter(item => insChildIds.includes(item.id));//获取所有子节点的docId
                let insChildDocInfoList = insChildRefDocInfo.map(item => ({
                    partDocId: item.docId,
                    partDocName: item.name
                }));
                materialSettingCommand.getInsMaterialInfoByDocInfos(insChildDocInfoList, res => {
                    this.calculateMaterialStatistics(res);
                    this.exportExcelFile();
                })
                //重新组织el-tree数据，根据组织的材料数据，计算当前装配下所有零件每种材料的用量
            } else {
                let msg = '请先选择一个需要导出的装配节点再导出';
                materialSettingCommand.eventBusAlertMsg(msg, 'warning');
            }
        },
        //获取全部孩子节点的ids
        getChildIds(data) {
            const ids = [];

            function traverse(node) {
                if (node.id !== undefined) {
                    ids.push(node.id);
                }
                if (node.children && node.children.length > 0) {
                    node.children.forEach(child => traverse(child))
                }
            }

            traverse(data);
            return ids;
        },
        calculateMaterialStatistics(data) {
            let materialList = data.flatMap(item => item.materialList);//将所有的对象展平
            let insMaterialInfoList = this.groupMaterialByNumber(materialList);//计算每种材料的totalArea
            let hasPartDocIdTableData = this.addPartDocIdToMaterialist(data);//组织tableData
            this.tableData = this.addTotalFieldToTableData(insMaterialInfoList, hasPartDocIdTableData);
        },
        //对当前实例重新按照材料编号分组,从而计算每种材料的totalArea
        groupMaterialByNumber(data) {
            let groupObjects = data.reduce((acc, obj) => {
                acc[obj.number] = [...(acc[obj.number] || []), obj];
                return acc;
            }, {})
            let groupArrays = Object.values(groupObjects);
            let insMaterialInfoList = [];
            if (groupArrays.length) {
                groupArrays.forEach(item => {
                    let counts = item.length;
                    let materialNumber = item[0].number;
                    let area = item[0].area;
                    let layer = item[0].layer;//当前材料的层数
                    let totalArea = counts * this.calculateCurrentArea(area, layer);
                    let materialInfo = {
                        mNumber: materialNumber,//材料编号
                        counts: counts,//每种材料在当前实例节点的总次数
                        area: area,//当前材料的area原始数据
                        totalArea: totalArea,//总面积
                    }
                    insMaterialInfoList.push(materialInfo);
                });
            }
            return insMaterialInfoList;
        },
        //计算当前一种材料的area
        calculateCurrentArea(str, layer) {
            let regex = /(?:δ[^*]*)?(\d+)(?:mm(?:\s*\*\s*(\d+))?|mm(?:\s*(\d+))?)/;
            let match = str.match(regex);
            if (match) {
                const num1 = parseInt(match[1], 10);
                let num2 = match[2] ? parseInt(match[2], 10) : (match[3] ? parseInt(match[3], 10) : 1);
                if (isNaN(num2)) {
                    num2 = 1;
                }
                return num1 * num2 * layer;
            } else {
                materialSettingCommand.eventBusAlertMsg('字符串格式不正确', 'warning');
            }
        },
        addPartDocIdToMaterialist(data) {
            let tableData = [];
            this.mergeExcel = [];
            data.forEach(item => {
                this.mergeExcel.push({
                    partDocName:item.partDocName,
                    materialCounts:item.materialList.length,
                });
                item.materialList.forEach(material => {
                    tableData.push({
                        partDocName: item.partDocName,
                        number: material.number,
                        level: material.level,
                        standard: material.standard,
                        area: material.area,
                        totalArea: null,
                    });
                });
            });
            return tableData;
        },
        addTotalFieldToTableData(materialList, tableData,excel) {
            for (let i = 0; i < materialList.length; i++) {
                for (let j = 0; j < tableData.length; j++) {
                    if (tableData[j].number === materialList[i].mNumber) {
                        tableData[j].totalArea = materialList[i].totalArea;
                        break;
                    }
                }
            }
            return tableData;
        },
        exportExcelFile() {
            let data = [];
            const strTitleLine = [
                this.$t('message.materialConsumeStatistics.partDocName'),
                this.$t('message.materialConsumeStatistics.materialNumber'),
                this.$t('message.materialConsumeStatistics.level'),
                this.$t('message.materialConsumeStatistics.standard'),
                this.$t('message.materialConsumeStatistics.area'),
                this.$t('message.materialConsumeStatistics.totalArea'),
            ];
            data.push(strTitleLine);
            this.tableData.forEach(item => {
                let strLine = [];
                strLine.push(item.partDocName);
                strLine.push(item.number);
                strLine.push(item.level);
                strLine.push(item.standard);
                strLine.push(item.area);
                strLine.push(item.totalArea);
                data.push(strLine);
            });

            if (data?.length > 0) {
                let workBook = XLSX.utils.book_new();
                let workSheet = XLSX.utils.aoa_to_sheet(data);
                // 设置合并单元格
                let elementCount = 0;
                let workSheetMergesList = [];
                this.mergeExcel.forEach(item => {
                    let count = item.materialCounts;
                    let merge = {
                        s: { r: elementCount + 1, c: 0 }, e: { r: elementCount + count, c: 0 }
                    };
                    workSheetMergesList.push(merge);
                    elementCount += count;
                });
                let columnWidths = [
                    { wch: 30 }, // 第一列宽度为10个字符宽度
                    { wch: 20 },
                    { wch: 20 },
                    { wch: 20 },
                    { wch: 30 },
                    { wch: 20 }
                ];
                workSheet['!cols'] = columnWidths;
                workSheet['!merges'] = workSheetMergesList;
                XLSX.utils.book_append_sheet(workBook, workSheet, "隔热隔声材料用量统计");
                let excelBuffer = XLSX.write(workBook, {bookType: 'xlsx', type: 'array'});
                let dataBlob = new Blob([excelBuffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8'});
                saveAs(dataBlob, '隔热隔声材料用量统计表.xlsx');
            } else {
                materialSettingCommand.eventBusAlertMsg("无隔热隔声材料用量统计数据，无法导出数据文件", "waring");
            }
        }
    },
}
</script>

<style scoped>
.wrap {
    font-size: 12px;
}
</style>